package customer

import (
	"counter-help/admin/server/global"
	"counter-help/admin/server/model/common/response"
	"counter-help/admin/server/model/customer"
	"counter-help/admin/server/model/customer/request"
	customerRes "counter-help/admin/server/model/customer/response"
	"counter-help/admin/server/model/system"
	"counter-help/admin/server/utils"
	"fmt"
	"github.com/gin-gonic/gin"
	"github.com/redis/go-redis/v9"
	"go.uber.org/zap"
	"math/rand"
	"time"
)

type CusUserPhoneLoginApi struct{}

func (p *CusUserPhoneLoginApi) PhoneLogin(c *gin.Context) {
	var phoneLoginReq request.PhoneLoginRequest
	err := c.ShouldBindJSON(&phoneLoginReq)
	if err != nil {
		global.GVA_LOG.Error("参数解析错误")
		response.FailWithMessage("参数解析错误:: "+err.Error(), c)
		return
	}
	if global.GVA_REDIS == nil {
		response.FailWithMessage("redis未开", c)
		return
	}
	//fmt.Println("Get", phoneLoginReq.Phone)
	v, err := global.GVA_REDIS.Get(c, phoneLoginReq.Phone).Result()
	if err != nil {
		response.FailWithMessage("Redis 中没有 其电话的 Code:: "+err.Error(), c)
		return
	}
	global.GVA_LOG.Info(phoneLoginReq.Phone + " Code Get:: " + v)
	if phoneLoginReq.Code != v {
		global.GVA_LOG.Error("验证码错误")
		response.FailWithMessage("验证码错误！", c)
		return
	}
	phoneUser, err := phoneLoginService.PhoneLogin(phoneLoginReq.Phone)
	if err != nil {
		response.FailWithMessage("手机登陆失败！Error: "+err.Error(), c)
		return
	}
	p.TokenNext(c, *phoneUser)
}

func (p *CusUserPhoneLoginApi) SendCode(c *gin.Context) {
	var phoneLoginReq request.SendCodeRequest
	if err := c.ShouldBindQuery(&phoneLoginReq); err != nil {
		global.GVA_LOG.Error("参数解析错误", zap.Error(err))
		response.FailWithMessage("参数解析错误: "+err.Error(), c)
		return
	}

	//判断来源
	if phoneLoginReq.Source != nil {
		source := *phoneLoginReq.Source
		if source == "login" {
			var user customer.CusUser
			err := global.GVA_DB.Where("username = ? ", phoneLoginReq.Phone).First(&user).Error
			if err != nil {
				global.GVA_LOG.Error("用户不存在，请先注册")
				response.FailWithMessage("用户不存在，请先注册", c)
				return
			}
		}
	}

	// 生成4位验证码
	code := generateVerificationCode()
	if code == -1 {
		global.GVA_LOG.Error("生成验证码失败")
		response.FailWithMessage("生成验证码失败", c)
		return
	}

	// 发送短信验证码
	err := phoneService.SendAliSms(
		phoneLoginReq.Phone,
		"SMS_475815043",
		fmt.Sprintf("{\"code\":\"%04d\"}", code)) // 确保验证码是4位数字
	if err != nil {
		global.GVA_LOG.Error("发送验证码失败", zap.Error(err))
		response.FailWithMessage("发送验证码失败: "+err.Error(), c)
		return
	}
	if global.GVA_REDIS == nil {
		response.FailWithMessage("redis未开", c)
		return
	}
	// 缓存验证码
	v, err := global.GVA_REDIS.Get(c, phoneLoginReq.Phone).Result()
	if err != nil {
		global.GVA_LOG.Info("Redis 不存在该手机号 Set:: " + string(code))
		global.GVA_REDIS.Set(c, phoneLoginReq.Phone, code, time.Second*60)

	} else {
		global.GVA_LOG.Info("验证码已存在，无需重新生成", zap.String("phone", phoneLoginReq.Phone))
		response.FailWithMessage("验证码已生成，且未过期: "+v, c)
		return
	}
	global.GVA_LOG.Info("验证码发送成功", zap.String("phone", phoneLoginReq.Phone))
	response.OkWithMessage("验证码发送成功！", c)
}

// TokenNext 登录以后签发jwt
func (p *CusUserPhoneLoginApi) TokenNext(c *gin.Context, user customer.CusUser) {
	token, claims, err := utils.CusLoginToken(&user)
	if err != nil {
		global.GVA_LOG.Error("获取token失败!", zap.Error(err))
		response.FailWithMessage("获取token失败", c)
		return
	}
	if !global.GVA_CONFIG.System.UseMultipoint {
		utils.SetToken(c, token, int(claims.RegisteredClaims.ExpiresAt.Unix()-time.Now().Unix()))
		response.OkWithDetailed(customerRes.LoginResponse{
			User:      user,
			Token:     token,
			ExpiresAt: claims.RegisteredClaims.ExpiresAt.Unix() * 1000,
		}, "登录成功", c)
		return
	}

	if jwtStr, err := jwtService.GetRedisJWT(user.Username); err == redis.Nil {
		if err := jwtService.SetRedisJWT(token, user.Username); err != nil {
			global.GVA_LOG.Error("设置登录状态失败!", zap.Error(err))
			response.FailWithMessage("设置登录状态失败", c)
			return
		}
		utils.SetToken(c, token, int(claims.RegisteredClaims.ExpiresAt.Unix()-time.Now().Unix()))
		response.OkWithDetailed(customerRes.LoginResponse{
			User:      user,
			Token:     token,
			ExpiresAt: claims.RegisteredClaims.ExpiresAt.Unix() * 1000,
		}, "登录成功", c)
	} else if err != nil {
		global.GVA_LOG.Error("设置登录状态失败!", zap.Error(err))
		response.FailWithMessage("设置登录状态失败", c)
	} else {
		var blackJWT system.JwtBlacklist
		blackJWT.Jwt = jwtStr
		if err := jwtService.JsonInBlacklist(blackJWT); err != nil {
			response.FailWithMessage("jwt作废失败", c)
			return
		}
		if err := jwtService.SetRedisJWT(token, user.GetUsername()); err != nil {
			response.FailWithMessage("设置登录状态失败", c)
			return
		}
		utils.SetToken(c, token, int(claims.RegisteredClaims.ExpiresAt.Unix()-time.Now().Unix()))
		response.OkWithDetailed(customerRes.LoginResponse{
			User:      user,
			Token:     token,
			ExpiresAt: claims.RegisteredClaims.ExpiresAt.Unix() * 1000,
		}, "登录成功", c)
	}
}

// 生成随机4位验证码
func generateVerificationCode() int {
	rand.Seed(time.Now().UnixNano()) // 初始化随机数种子
	code := rand.Intn(9000) + 1000   // 确保生成1000到9999之间的随机数
	return code
}

// 类型转换
func interfaceToInt(v interface{}) (i int) {
	switch v := v.(type) {
	case int:
		i = v
	default:
		i = 0
	}
	return
}
